﻿using Games.WPF.Graphics;
using System;
using System.ComponentModel;
using Games.WPF.Utility;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace Robots
{
    /// <summary>
    /// Interaction logic for Entity.xaml
    /// </summary>
    public partial class Entity : Sprite
    {
        #region Constructors

        public Entity()
            : base()
        {
            InitializeComponent();

            Dialogs = new List<Window>();

            Loaded += new RoutedEventHandler(Entity_Loaded);
        }

        #endregion

        #region Properties

        /// <summary>
        /// A collection of dialogs currently in use by this entity.
        /// </summary>
        private List<Window> Dialogs { get; set; }

        #region Movement Properties

        private double X
        {
            get
            {
                if (Parent is Canvas)
                {
                    return Canvas.GetLeft(this);
                }
                else
                {
                    return double.NaN;
                }
            }
            set
            {
                if (X != value)
                {
                    if (Parent is Canvas)
                    {
                        Canvas.SetLeft(this, value);
                        PropertyHasChanged("X");
                    }
                }
            }
        }

        private double Y
        {
            get
            {
                if (Parent is Canvas)
                {
                    return Canvas.GetTop(this);
                }
                else
                {
                    return double.NaN;
                }
            }
            set
            {
                if (Y != value)
                {
                    if (Parent is Canvas)
                    {
                        Canvas.SetTop(this, value);
                        PropertyHasChanged("Y");
                    }
                }
            }
        }

        private Vector Velocity { get; set; }

        private int LastUpdateTime { get; set; }

        #endregion

        #region Scripting Properties

        private ScriptEngine Engine { get; set; }

        public string CreateScript
        {
            get
            {
                return (string)GetValue(CreateScriptProperty);
            }
            set
            {
                if (CreateScript != value)
                {
                    SetValue(CreateScriptProperty, value);
                    PropertyHasChanged("CreateScript");
                }
            }
        }

        public static readonly DependencyProperty CreateScriptProperty =
            DependencyProperty.Register("CreateScript", typeof(string), typeof(Entity), new PropertyMetadata(string.Empty));

        public string UpdateScript
        {
            get
            {
                return (string)GetValue(UpdateScriptProperty);
            }
            set
            {
                if (DestroyScript != value)
                {
                    SetValue(UpdateScriptProperty, value);
                    PropertyHasChanged("UpdateScript");
                }
            }
        }

        public static readonly DependencyProperty UpdateScriptProperty =
            DependencyProperty.Register("UpdateScript", typeof(string), typeof(Entity), new PropertyMetadata(string.Empty));

        public string DestroyScript
        {
            get
            {
                return (string)GetValue(DestroyScriptProperty);
            }
            set
            {
                if (DestroyScript != value)
                {
                    SetValue(DestroyScriptProperty, value);
                    PropertyHasChanged("DestroyScript");
                }
            }
        }

        public static readonly DependencyProperty DestroyScriptProperty =
            DependencyProperty.Register("DestroyScript", typeof(string), typeof(Entity), new PropertyMetadata(string.Empty));

        #endregion

        #endregion

        #region Methods

        private void CloseAllDialogs()
        {
            foreach (Window dlg in Dialogs)
            {
                dlg.Close();
            }
            Dialogs.Clear();
        }

        public void Destroy()
        {
            CloseAllDialogs();
            Engine.Execute(DestroyScript);
            (Parent as Panel).Children.Remove(this);
        }

        public void Reset()
        {
            StopMoving();

            Engine = new ScriptEngine(this);
            Engine.Execute(CreateScript);
        }

        public void RemoveDialog(Window dlg)
        {
            if (Dialogs.Contains(dlg))
            {
                Dialogs.Remove(dlg);
            }
        }

        #region Movement Methods

        public void AccelerateTo(double x, double y)
        {
            Velocity = new Vector(x, y);
        }

        public void Accelerate(double x, double y)
        {
            AccelerateTo(Velocity.X + x, Velocity.Y + y);
        }

        public void StopMoving()
        {
            AccelerateTo(0, 0);
        }

        private void Move()
        {
            if (LastUpdateTime != 0)
            {
                double timeDelta = Timer.GetSystemTimeMS() - LastUpdateTime;
                double speedModifier = (Speed / 10.0) / 100.0;
                double xDelta = timeDelta * Velocity.X * speedModifier;
                double yDelta = timeDelta * Velocity.Y * speedModifier;

                if ((xDelta != 0) || (yDelta != 0))
                {
                    Move(xDelta, yDelta);
                }
                if (timeDelta * speedModifier >= 1)
                {
                    LastUpdateTime = Timer.GetSystemTimeMS();
                }
            }
            else
            {
                LastUpdateTime = Timer.GetSystemTimeMS();
            }
        }

        public void Move(double x, double y)
        {
            MoveTo(X + Velocity.X, Y + Velocity.Y);
        }

        public void MoveTo(double x, double y)
        {
            X = x;
            Y = y;
        }

        private void OpenDialog(Window dlg)
        {
            dlg.Show();
            Dialogs.Add(dlg);
        }

        #endregion

        #endregion

        #region Event Handlers

        private void Entity_Loaded(object sender, RoutedEventArgs e)
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                AnimationTimer.Tick += new EventHandler(RunScript_Tick);
                AnimationTimer.Tick += new EventHandler(UpdatePosition_Tick);
                Reset();
            }
        }

        private void removeMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Destroy();
        }

        private void RunScript_Tick(object sender, EventArgs e)
        {
            try
            {
                Engine.Execute(UpdateScript);
            }
            catch (Exception ex)
            {
                string s = ex.Message;
            }
        }

        private void UpdatePosition_Tick(object sender, EventArgs e)
        {
            Move();
        }

        private void editCreateScriptMenuItem_Click(object sender, RoutedEventArgs e)
        {
            OpenDialog(new EditScript(this, "CreateScript"));
        }

        private void editDestroyScriptMenuItem_Click(object sender, RoutedEventArgs e)
        {
            OpenDialog(new EditScript(this, "DestroyScript"));
        }

        private void editUpdateScriptMenuItem_Click(object sender, RoutedEventArgs e)
        {
            OpenDialog(new EditScript(this, "UpdateScript"));
        }

        private void resetMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        #endregion
    }
}